<template>
	<view v-loading="loading">
		<view id="crud-top" class="top bg-white p-15px">
			<el-form ref="crudFormRef" :model="crudForm" :rules="rules">
				<dx-grid :collapsed="collapsed" :gap="[20, 0]" :cols="{ xs: 1, sm: 2, md: 3, lg: 4, xl: 5 }">
					<dx-grid-item :index="0">
						<el-form-item label="云函数:" prop="functionPath">
							<el-select v-model="crudForm.functionPath" placeholder="请选择云函数" clearable>
								<el-option v-for="item in afterendList" :key="item.value" :label="item.label" :value="item.value"></el-option>
							</el-select>
						</el-form-item>
					</dx-grid-item>
					<dx-grid-item :index="1">
						<el-form-item label="前端模块:" prop="frontendPath">
							<el-select v-model="crudForm.frontendPath" placeholder="请选择前端模块" clearable>
								<el-option v-for="item in frontendList" :key="item.value" :label="item.label" :value="item.value"></el-option>
							</el-select>
						</el-form-item>
					</dx-grid-item>
					<dx-grid-item :index="2">
						<el-form-item label="文件名称:" prop="fileName">
							<el-input v-model="crudForm.fileName" placeholder="请输入文件名称" clearable></el-input>
						</el-form-item>
					</dx-grid-item>
					<dx-grid-item :index="3">
						<el-form-item label="是否读取schema:" prop="isSchema">
							<el-switch v-model="crudForm.isSchema"></el-switch>
						</el-form-item>
					</dx-grid-item>
					<dx-grid-item :index="4">
						<el-form-item label="数据表名称:" prop="tableName">
							<template v-if="crudForm.isSchema">
								<el-select v-model="crudForm.tableName" placeholder="请选择数据表名称" clearable @change="getDatabase">
									<el-option v-for="item in tableList" :key="item.value" :label="item.label" :value="item.value"></el-option>
								</el-select>
							</template>
							<template v-else>
								<el-input v-model="crudForm.tableName" placeholder="请输入数据表名称" clearable></el-input>
							</template>
						</el-form-item>
					</dx-grid-item>
					<dx-grid-item :index="5">
						<!-- 是否强制覆盖 -->
						<el-form-item label="是否强制覆盖:" prop="isCover">
							<el-switch v-model="crudForm.isCover"></el-switch>
						</el-form-item>
					</dx-grid-item>
					<dx-grid-item :index="6">
						<el-form-item label="是否是多模块应用:" prop="isMultiModule">
							<el-switch v-model="crudForm.isMultiModule"></el-switch>
						</el-form-item>
					</dx-grid-item>
					<dx-grid-item :index="7" v-if="crudForm.isMultiModule">
						<el-form-item label="模块名称:" prop="moduleName">
							<el-input v-model="crudForm.moduleName" placeholder="请输入模块名称" clearable></el-input>
						</el-form-item>
					</dx-grid-item>
					<dx-grid-item :index="8">
						<el-form-item label="菜单名称:" prop="menuName">
							<el-input v-model="crudForm.menuName" placeholder="请输入菜单名称" clearable></el-input>
						</el-form-item>
					</dx-grid-item>
					<dx-grid-item :index="9">
						<el-form-item label="父级菜单:" prop="parentMenu">
							<dx-tree-select
								v-model="crudForm.parentMenu"
								nodeKey="menu_id"
								url="menu/index"
								placeholder="请选择父级菜单"
								:props="{ label: 'name', children: 'children' }"
							></dx-tree-select>
						</el-form-item>
					</dx-grid-item>
					<dx-grid-item suffix>
						<div class="operation">
							<el-button type="primary" @click="createCrud">
								<dx-icon color="#ffffff" size="16" name="searchIcon"></dx-icon>
								<text>生成</text>
							</el-button>
							<el-button type="info" @click="reset">
								<dx-icon color="#ffffff" size="16" name="resetIcon"></dx-icon>
								<text>重置</text>
							</el-button>
							<el-button type="primary" class="search-isOpen" @click="collapsed = !collapsed">
								{{ collapsed ? '展开' : '折叠' }}
								<dx-icon color="#ffffff" size="16" :name="collapsed ? 'double-down' : 'double-up'"></dx-icon>
							</el-button>
						</div>
					</dx-grid-item>
				</dx-grid>
			</el-form>
		</view>
		<view class="crud mt-15px flex justify-between">
			<view class="left">
				<view class="bg-white px-15px">
					<el-collapse v-model="activeName">
						<el-collapse-item :title="item.label" :name="`${index + 1}`" v-for="(item, index) in componentList" :key="index">
							<draggable
								:sort="false"
								class="list flex flex-wrap"
								:list="item.list"
								:group="{ name: 'crud', pull: 'clone', put: false }"
								itemKey="index"
								:clone="cloneHandle"
							>
								<template #item="{ element }">
									<view class="item m-5px px-8px py-3px">{{ element.title }}</view>
								</template>
							</draggable>
						</el-collapse-item>
					</el-collapse>
				</view>
			</view>
			<view class="middle flex-1 mx-15px">
				<view class="bg-white p-15px">
					<draggable class="component" v-model="formList" item-key="index" group="crud">
						<template #item="{ element, index }">
							<view class="item flex items-center px-10px py-5px" :class="{ activate: currentIndex === index }" @click="selectCurrentItem(index)">
								<view class="flex flex-1 flex-between">
									<view class="flex items-center flex-1">
										<view class="label">字段名：</view>
										<el-input v-model="element.name" placeholder="请输入字段名称" clearable></el-input>
									</view>
									<view class="flex items-center flex-1 ml-15px">
										<view class="title">字段标题：</view>
										<el-input v-model="element.title" placeholder="请输入字段标题" clearable></el-input>
									</view>
								</view>
								<view class="flex ml-100px">
									<el-button type="danger" size="small" @click.stop="remove(index)">
										<dx-icon size="16" name="delete" color="#ffffff"></dx-icon>
									</el-button>
								</view>
							</view>
						</template>
						<template #footer>
							<view v-if="!formList.length" style="color: darkgray; text-align: center">拖动左侧组件至此～</view>
						</template>
					</draggable>
				</view>
			</view>
			<view class="right">
				<el-scrollbar>
					<view :style="{ height: crudBoxHeight }">
						<attribute :currentItem="currentItem"></attribute>
					</view>
				</el-scrollbar>
			</view>
		</view>
	</view>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, nextTick, onMounted, onUnmounted, watch } from 'vue';
import { post } from './service';
import { axios } from '@/uni_modules/dx-admin/api/index';
import draggable from 'vuedraggable';
import attribute from './attribute.vue';
import { componentList } from './useCrud';

const loading = ref(false);
const collapsed = ref(true);
const crudFormRef = ref();
const crudBoxHeight = ref('500px');
// crud 高度自适应
const getCrudBoxHeight = function () {
	let crudTopHeight = document.querySelector('#crud-top')?.clientHeight || 0;
	crudBoxHeight.value = document.documentElement.clientHeight - 130 - crudTopHeight + 'px';
};
onMounted(() => {
	nextTick(() => {
		getCrudBoxHeight();
	});
	window.addEventListener('resize', getCrudBoxHeight);
});
onUnmounted(() => {
	window.removeEventListener('resize', getCrudBoxHeight);
});
watch(
	() => collapsed.value,
	() => {
		nextTick(() => {
			getCrudBoxHeight();
		});
	}
);
//简单深拷贝
const cloneSingle = (item: any) => JSON.parse(JSON.stringify(item));
const dxUpCrudForm = uni.getStorageSync('dxUpCrudForm');
const crudForm = reactive<any>({
	functionPath: dxUpCrudForm?.functionPath || '',
	frontendPath: dxUpCrudForm?.frontendPath || '',
	fileName: '',
	tableName: '',
	isSchema: dxUpCrudForm?.isSchema || false,
	isCover: dxUpCrudForm?.isCover || false,
	isMultiModule: dxUpCrudForm?.isMultiModule || false,
	moduleName: dxUpCrudForm?.moduleName || '',
	menuName: '',
	parentMenu: dxUpCrudForm?.parentMenu || '',
});
const rules = reactive<any>({
	functionPath: [{ required: true, message: '请选择云函数', trigger: ['blur', 'change'] }],
	frontendPath: [{ required: true, message: '请选择前端模块', trigger: ['blur', 'change'] }],
	fileName: [{ required: true, message: '请输入生成的文件名称', trigger: ['blur', 'change'] }],
	tableName: [{ required: true, message: '请输入数据表名称', trigger: ['blur', 'change'] }],
	moduleName: [{ required: true, message: '请输入模块名称', trigger: ['blur', 'change'] }],
	menuName: [{ required: true, message: '请输入菜单名称', trigger: ['blur', 'change'] }],
});
const afterendList = ref<any>([]);
const frontendList = ref<any>([]);
const tableList = computed(() => {
	return afterendList.value.find((v: any) => v.value === crudForm.functionPath)?.database.map((item: any) => ({ label: item, value: item })) || [];
});

const activeName = ref(['1', '2']);
//表单列表
const formList = ref<any>([]);
// 数据格式
const dataJson = {
	type: '', //类型
	name: '', //字段名
	title: '', //字段标题
	attrs: {
		type: 'string',
		value: '',
	},
	form: {
		clearable: true,
		rules: [],
		upload_max: 1,
		options: [],
		// 是否多选
		multiple: false,
		dateMode: 'date',
		min: '',
		max: '',
		step: 1,
		isRange: false,
	},
	table: {
		operator: true, //是否搜索
		visible: true, //表格是否展示
		render: '', //自定义渲染
		formatter: '', //自定义格式化
		minWidth: 100, //最小宽度
	},
};
// 当前项
const currentItem = ref<any>({ ...cloneSingle(dataJson) });
const currentIndex = ref(-1);
// 选择当前项
function selectCurrentItem(index: number) {
	currentItem.value = formList.value[index];
	currentIndex.value = index;
}
// 删除
function remove(index: number) {
	formList.value.splice(index, 1);
}
// 克隆
function cloneHandle({ name }: any) {
	let data: any = {
		...cloneSingle(dataJson),
		type: name,
	};
	if (name === 'number') {
		data.attrs.type = 'number';
		data.attrs.value = 0;
	} else if (name === 'dx-array') {
		data.attrs.type = 'array';
		data.attrs.value = [];
	}
	return data;
}
// 获取数据表字段
function getDatabase() {
	let funcRow = afterendList.value.find((item: any) => item.value === crudForm.functionPath);
	if (!funcRow || !crudForm.tableName) return;
	post('http://localhost:5088/database', {
		funcPath: funcRow.value,
		tableName: crudForm.tableName,
	}).then((res: any) => {
		console.log(res);
		if (res?.properties !== void 0) {
			// 清空表单列表
			formList.value = [];
			for (let [key, item] of Object.entries(res.properties)) {
				if (key !== '_id') {
					let json: any = {
						...cloneSingle(dataJson),
						title: (item as any).description,
						name: key,
					};
					// 判断类型
					switch ((item as any).bsonType) {
						case 'object':
							json.type = 'object';
							json.attrs.type = 'object';
							json.attrs.value = {};
							break;
						case 'bool':
							json.type = 'switch';
							json.attrs.type = 'boolean';
							json.attrs.value = false;
							break;
						case 'array':
							json.type = 'dx-array';
							json.attrs.type = 'array';
							json.attrs.value = [];
							break;
						case 'int':
						case 'double':
							json.attrs.value = 0;
						case 'timestamp':
							json.type = 'number';
							json.attrs.type = 'number';
							break;
						default:
							json.type = 'text';
							json.attrs.type = 'string';
							json.attrs.value = '';
							break;
					}
					formList.value.push(json);
				}
			}
		}
	});
}
// 获取云函数
post('http://localhost:5088/').then((res: any) => {
	afterendList.value = res.afterend;
	frontendList.value = res.frontend;
});
function reset() {
	crudFormRef.value.resetFields();
}
function createCrud() {
	crudFormRef.value.validate((valid: boolean) => {
		if (valid) {
			if (formList.value.some((item: any) => !item.name)) {
				return ElMessage.error('请填写完整字段名称');
			}
			if (formList.value.some((item: any) => !item.title)) {
				return ElMessage.error('请填写完整字段标题');
			}
			let funcRow = afterendList.value.find((item: any) => item.value === crudForm.functionPath);
			let frontendRow = frontendList.value.find((item: any) => item.value === crudForm.frontendPath);
			loading.value = true;
			// 设置上一次缓存
			uni.setStorageSync('dxUpCrudForm', {
				functionPath: crudForm.functionPath,
				frontendPath: crudForm.frontendPath,
				isSchema: crudForm.isSchema,
				isCover: crudForm.isCover,
				isMultiModule: crudForm.isMultiModule,
				moduleName: crudForm.moduleName,
				parentMenu: crudForm.parentMenu,
			});
			// uni.setStorageSync('frontendPath', crudForm.frontendPath);
			post('http://localhost:5088/create', { ...crudForm, params: formList.value, frontendModule: frontendRow.label, funcName: funcRow.label }).then(
				(res: any) => {
					console.log(res);
					if (res === 'success') {
						// 创建菜单数据
						axios
							.send('menu/save', 'dx-func-admin', {
								name: crudForm.menuName || crudForm.fileName,
								parent_id: crudForm.parentMenu || '',
								icon: 'application-menu',
								menu_id: `${frontendRow.label.replace(/\_|\-/g, '.')}.${crudForm.fileName}`,
								sort: 0,
								url: `/uni_modules/${frontendRow.label}/pages/${crudForm.fileName}/${crudForm.fileName}`,
								is_link: false,
								enable: true,
								comment: '',
							})
							.then((res) => {
								console.log(res);
							})
							.catch((err) => {
								console.log(err);
							})
							.finally(() => {
								loading.value = false;
								ElMessage.success('创建成功');
								// 刷新页面
								// window.location.reload();
							});
						// 创建权限数据
					} else {
						loading.value = false;
					}
				}
			);
		}
	});
}
</script>
<style lang="scss" scoped>
.top {
	min-height: 60px;
}
.left,
.right {
	width: 250px;
}

.middle {
	.component {
		min-height: 50vh;
	}
	.item {
		&:not(:last-child) {
			margin-bottom: 6px;
		}
		.label {
			width: 80px;
		}
		.title {
			width: 100px;
		}
	}
}
.left,
.right,
.middle {
	.item {
		border: 1px dashed #dedede;
		color: var(--el-text-color-regular);
		font-size: 14px;
		border-radius: 5px;
		cursor: pointer;
		&:hover {
			border-color: var(--el-color-primary);
		}
		&.activate {
			border-color: var(--el-color-primary);
		}
	}
}
::v-deep {
	.el-select {
		width: 100%;
	}
}
</style>
